#include "./app_can.h"
#include "./app_adc.h"
#include "./app_alarm.h"
#include "./app_flash.h"
#include "./app_dac.h"
#include "./app_device.h"
struct can_dev_t *comm_dev;//通信设备
extern uint16_t voutSetVal,ioutSetVal;
struct can_msg_ext_id_t  mgs_ext_id;
uint8_t limit_flag = 0;//限制标志 bit0 限流 bit1 均流
uint16_t  canVoutSetVal = 0;//设置值
uint16_t  canLimitIval = 0;//限流值
uint16_t canAvrIoutval;
uint8_t vtest = 0;
extern uint32_t canSlaveAddr;

void app_can_init(void)
{	
	canSlaveAddr=app_load_can_addr_default();
    can_init(&comm_dev);
    //读取flsah 地址
    //设置地址
    comm_dev->set_src_id(comm_dev,store_device.dev_param.param.id);

}
/**
 * 根据输入源地址目的地址和版本号得到一个扩展地址
*/
uint32_t can_set_msg_ext_id(void)
{
     /**
     * bit | 27:22  | 21:20  |   19:0     |
     *     | 命令号 |目的地址|   源地址   |
     *     | 6bits  |2bits   |   20bits   |
     *    
    */
    uint32_t ret = 0;
    //mgs_ext_id.cmd=mgs_ext_id.cmd&0x3f;
    ret |=(mgs_ext_id.cmd<<22)|(mgs_ext_id.master_addr<<20)|mgs_ext_id.slave_addr;
    return ret;
    
}

/**
 * @brief 处理接收的广播指令逻辑
 * 
 * @param dev 
 * @param cmd 
 * @return int 
 */
static int app_can_broadcast_handler(struct can_dev_t *dev)
{
    switch(comm_dev->obj.cmd_num)
    {
        case CAN_CMD_BROADCAST_HOST_SET_VOUT:  // 设置电压值 
						//此值为扩大10倍的值，在设置时应设置到0.1
            canVoutSetVal = comm_dev->obj.RX[0]|(comm_dev->obj.RX[1]<<8);
						
        break;
		case CAN_CMD_BROADCAST_HOST_SET_IOUT:  // 设置电流值

		vtest = comm_dev->obj.RX[0];
		break;
        case CAN_CMD_BROADCAST_HOST_SET_DEV:
         //设置开关机
         if(comm_dev->obj.RX[0]>0){
            mod_device->set_power(mod_device,1);
         }
         else{
            mod_device->set_power(mod_device,0);    
         }
				
        break;
        default:
        break;
    }
    return 0;
}


static int app_can_response_mod_vout(struct can_dev_t *dev)
{
    uint8_t txbuf[8]={0};
    uint16_t tmp;
   // mgs_ext_id.err = CAN_MSG_OK;
    //mgs_ext_id.ver = CAN_MSG_VER_A;
    mgs_ext_id.cmd = CAN_CMD_DEVICE_HOST_GET_MOD_VOUT_IOUT;
    mgs_ext_id.master_addr = CAN_MASTER_ADDR;
    mgs_ext_id.slave_addr =canSlaveAddr;
    dev->obj.tx_id=can_set_msg_ext_id();
    dev->set_ide(dev,1);//设置扩展帧
    tmp = (uint16_t)(VolVout*10);

    if((mod_device->get_dev_state(mod_device))==0)//最高位用于设备状态
    {
        tmp &=~(1<<15); 
		
    }
    else{
        tmp |= (1<<15);
			
    }
		
    txbuf[0]= tmp;
    txbuf[1]= tmp>>8;
    tmp = (uint16_t)(VolIout*10);
    txbuf[2]= tmp;
    txbuf[3]= tmp>>8;
    tmp = (uint16_t)(VolVin*10);
    txbuf[4]= tmp;
    txbuf[5]= tmp>>8;   
    txbuf[6] = (uint8_t)VolTemp;
    txbuf[7] = warn_device->fault_flag_buf[0];
    dev->tx_msg_func(dev,txbuf,8);//返回当前设备状态 
	
	return 0;
}


/**
 * @brief 处理单机指令
 * 
 * @param dev 
 * @return int 
 */
static int app_can_slave_handler(struct can_dev_t *dev)
{
    switch(comm_dev->obj.cmd_num)
    {
        case CAN_CMD_DEVICE_HOST_SET_VOUT: // 设置电压 电流值 
						//此值为扩大10倍的值，在设置时应设置到0.1
           // voutSetVal = comm_dev->obj.RX[0]|(comm_dev->obj.RX[1]<<8);
           // ioutSetVal = comm_dev->obj.RX[2]|(comm_dev->obj.RX[3]<<8);
           canVoutSetVal = comm_dev->obj.RX[0]|(comm_dev->obj.RX[1]<<8);

        break;  
        case CAN_CMD_DEVICE_HOST_SET_DEV_POWER :/*!< 设置开关机*/
                 //设置开关机
         if(comm_dev->obj.RX[0]>0){
            mod_device->set_power(mod_device,1);
         }
         else{
           mod_device->set_power(mod_device,0);    
         }
				
        break;
        case CAN_CMD_DEVICE_HOST_GET_MOD_STATUS :/*!< 读取告警状态*/

        break;
        case CAN_CMD_DEVICE_HOST_GET_MOD_VOUT_IOUT:/*!< 读取电压电流*/
							limit_flag = comm_dev->obj.RX[0];
							if(limit_flag&0x01)//是否限流
							{
								//canVoutSetVal = comm_dev->obj.RX[1]|(comm_dev->obj.RX[2]<<8);								
							}
							if(limit_flag&0x02)//是否均流
							{
								canAvrIoutval = comm_dev->obj.RX[3]|(comm_dev->obj.RX[4]<<8);	
							}
							else{
								canAvrIoutval= 0;
							}
              app_can_response_mod_vout(comm_dev);
	
										
        break;
        default:
        break;
    }
    return 0;
}
/*
* @ 探针函数 ，用于 探测主机
 */

static int can_probe_master(struct can_dev_t *dev)
{
    uint8_t txbuf[8]={0};
    uint16_t tmp;
    mgs_ext_id.cmd = 0x3f;
    mgs_ext_id.master_addr = CAN_MASTER_PROBE_ADDR;
    mgs_ext_id.slave_addr   =canSlaveAddr;
    dev->obj.tx_id=can_set_msg_ext_id();
    dev->set_ide(dev,1);//设置扩展帧
    txbuf[0]= 0;
    txbuf[1]= 1;
    txbuf[2]= 2;
    txbuf[3]= 3;
    txbuf[4]= 4;
    txbuf[5]= 5;   
    txbuf[6] =6; 
    txbuf[7] =7; 
    dev->tx_msg_func(dev,txbuf,8);//返回当前设备状态 
	
	return 0;
}

uint16_t appCanCount =0;//500ms 加1 
/*
* @can 探针 每个3s 发送探针消息 判断主机本机地址是否在主机地址列表中
 */
void app_can_probe(void)
{
	if(appCanCount>6)//3s
	{
				appCanCount = 0;
				can_probe_master(comm_dev);
	}

}
/**
 * @brief can 通信逻辑运算
 *        协议参考doc/can_protocol.md
 * 
 */
void app_can_loop_func(void)
{
    uint32_t ext_id;
    app_can_probe();
    if(comm_dev->rx_finish(comm_dev))
    {
        
#if 0
			/**
         * @brief 解析扩展帧目的地址
         * 
         */

        ext_id = comm_dev->obj.rx_id;
        comm_dev->obj.src_addr=  ext_id&0xff;
        comm_dev->obj.dst_addr= (ext_id>>8)&0xff;
        comm_dev->obj.cmd_num = (ext_id>>16)&0x3f;
        comm_dev->obj.dev_num = (ext_id>>22)&0x0f;
        comm_dev->obj.err_num = (ext_id>>26)&0x07;
#else
			  //bit 22~27 cmd 
			  //bit 21~20 src
	      ext_id = comm_dev->obj.rx_id;
			  comm_dev->obj.slave_addr =  ext_id&0x000fffff;//本机地址
        comm_dev->obj.master_addr = (ext_id>>20)&0x3;//取2bit
        comm_dev->obj.cmd_num = (ext_id>>22)&0xef;//取7bit
#endif 
			  if(comm_dev->obj.master_addr==CAN_BROADCAST_ADDR)//广播命令
        {
           app_can_broadcast_handler(comm_dev);
				}
        else if(comm_dev->obj.slave_addr ==canSlaveAddr)//单机命令
        {
					 // comm_dev->running_flag += 1;
           // if(comm_dev->running_flag>CAN_TIMEOUT_VALUE)comm_dev->running_flag=CAN_TIMEOUT_VALUE;
            app_can_slave_handler(comm_dev);
        }
        else{

        }
    }
}


